/****************************************************************************
** @brief concrete state subcalsses
****************************************************************************/

#include "readyStatus.h"
#include "idleStatus.h"
#include "startingStatus.h"
#include "faultStatus.h"

#include "../hciMain.h"
#include "../cardMain.h"
#include "../oiovMain.h"
#include "../oiovCallback.h"
#include "../controllerMain.h"
#include "../card/abstractCard.h"
#include "../recordMain.h"

#include "../../controller/controller_can.h"

#include <QDebug>
#define READYSTATE_DEBUG

#define START_TIMEOUT   (100)

Status *ReadyStatus::instance_ = nullptr;

ReadyStatus::ReadyStatus() : Status()
{
    state_ = Status::kReady;
}

ReadyStatus::~ReadyStatus()
{

}

Status *ReadyStatus::instance()
{
    if (nullptr == instance_) {
        instance_ = new ReadyStatus();
    }
    return instance_;
}

void ReadyStatus::Process(Gun *g)
{
    time_t _time;
    struct tm *_tm;

    time(&_time);
    _tm = localtime(&_time); //current time

    size_t i;
    QString str;
    QVariantHash vhash;
    unsigned char no = g->gun_number();

    if ((CONGUNNOA != no) && (CONGUNNOB != no)) {
        return;
    }

    no = no - CONGUNNOA;

#if defined(READYSTATE_DEBUG)
    static int count = 0;
    if (++count >= 5 * 1000 / 100) {
        count = 0;
        qDebug() << "[CHARGE]->" << (no ? "No.b" : "No.a") << "ready state...";
    }
#endif

    switch (ControllerParserMain::con_telecommand[no].work_state) {
    case WAIT_STATE:
        //连接车辆
        if (0 == ControllerParserMain::con_telecommand[no].connect_bus) {
            if (OiovReqMain::AppStartChargeService(no)) {
                HciMain::ClearStartChargeService(no); //清除标志位
                HciMain::ClearStopChargeService(no); //清除标志位
                CardMain::ClearStartChargeService(no); //清除标志位
                CardMain::ClearStopChargeService(no); //清除标志位
                OiovReqMain::ClearAppStartChargeService(no); //清除标志位
                OiovReqMain::ClearAppStopChargeService(no); //清除标志位
                OiovReqMain::ClearCardAuthStartChargeService(no); //清除标志位
                ControllerParserMain::ClearStopChargingService(no); //清除标志位

                qDebug() << "[CHARGE]->" << (no ? "No.b" : "No.a") << "app start charging ( start time:" << _time << ")";

                g->set_start_time(_time);
                g->set_stop_time(g->start_time());
                g->set_charge_time(g->start_time() - g->stop_time());
                g->set_start_timeout(START_TIMEOUT * 1000 / 100);

                ChangeState(g, StartingStatus::instance()); //切换到开始充电

#if defined(READYSTATE_DEBUG)
                qDebug() << "[CHARGE]->" << (no ? "No.b" : "No.a") << "ready -> starting";
#endif

                //start charging - 告诉控制器可以开始充电了
                ControllerSendMain::con_start_charg[no].gnu_no = no + CONGUNNOA;
                ControllerSendMain::con_start_charg[no].ctrl_flag = 1; //1: Enable , 2: Disenable
                ControllerSendMain::con_start_charg[no].aps = BaseConfigure::apu24(no) ? 0x02 : 0x01; //1: 12V , 2: 24V
                memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_START_CHARG]), 0x00, sizeof(con_frame_info_t));
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].gunno = no + CONGUNNOA;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].cycle = 250;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].count = 0;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].timeout = 5000;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].time = controller_time();
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].pduformat = CON_PDUFORMAT_START_CHARG;

                //data - 填充充电枪实时数据
                memset(OiovCallback::ops_property_charge_data[no].serial_number, 0x00, sizeof(OiovCallback::ops_property_charge_data[no].serial_number));
                memcpy(OiovCallback::ops_property_charge_data[no].serial_number, OiovCallback::ops_active_service_start_charging_app[no].serial_number, sizeof(OiovCallback::ops_property_charge_data[no].serial_number));
                memset(OiovCallback::ops_property_charge_data[no].pill_number, 0x00, sizeof(OiovCallback::ops_event_bill[no].pill_number));
                memcpy(OiovCallback::ops_property_charge_data[no].pill_number, OiovCallback::ops_active_service_start_charging_app[no].pill_number, sizeof(OiovCallback::ops_property_charge_data[no].pill_number));
                OiovCallback::ops_property_charge_data[no].connect_gun = OiovCallback::OPS_GUN_CONNECT_STATE_YES;
                OiovCallback::ops_property_charge_data[no].output_voltage = 0x00;
                OiovCallback::ops_property_charge_data[no].output_current = 0x00;
                OiovCallback::ops_property_charge_data[no].line_temp = 50;
                OiovCallback::ops_property_charge_data[no].soc = 0;
                OiovCallback::ops_property_charge_data[no].battery_max_temp = 50;
                OiovCallback::ops_property_charge_data[no].charging_time = 0x00;
                OiovCallback::ops_property_charge_data[no].remaining_charging_time = 0x00;
                OiovCallback::ops_property_charge_data[no].charging_elect = 0x00;
                OiovCallback::ops_property_charge_data[no].loss_calculation_elect = OiovCallback::ops_property_charge_data[no].charging_elect;
                OiovCallback::ops_property_charge_data[no].charging_fee = 0x00;
                OiovCallback::ops_property_charge_data[no].fault = 0x00;

                //data - 填充交易记录
                memset(OiovCallback::ops_event_bill[no].serial_number, 0x00, sizeof(OiovCallback::ops_event_bill[no].serial_number));
                memcpy(OiovCallback::ops_event_bill[no].serial_number, OiovCallback::ops_active_service_start_charging_app[no].serial_number, sizeof(OiovCallback::ops_event_bill[no].serial_number));
                memset(OiovCallback::ops_event_bill[no].pill_number, 0x00, sizeof(OiovCallback::ops_event_bill[no].pill_number));
                memcpy(OiovCallback::ops_event_bill[no].pill_number, OiovCallback::ops_active_service_start_charging_app[no].pill_number, sizeof(OiovCallback::ops_event_bill[no].pill_number));
                OiovCallback::ops_event_bill[no].start_time.cp56time2a_tm.year  = _tm->tm_year + 1900 - 2000;
                OiovCallback::ops_event_bill[no].start_time.cp56time2a_tm.month = _tm->tm_mon + 1;
                OiovCallback::ops_event_bill[no].start_time.cp56time2a_tm.mday  = _tm->tm_mday;
                OiovCallback::ops_event_bill[no].start_time.cp56time2a_tm.wday  = _tm->tm_wday;
                OiovCallback::ops_event_bill[no].start_time.cp56time2a_tm.hour  = _tm->tm_hour;
                OiovCallback::ops_event_bill[no].start_time.cp56time2a_tm.min   = _tm->tm_min;
                OiovCallback::ops_event_bill[no].start_time.cp56time2a_tm.msec  = _tm->tm_sec * 1000;
                OiovCallback::ops_event_bill[no].stop_time = OiovCallback::ops_event_bill[no].start_time;
                OiovCallback::ops_event_bill[no].sharp_unit_fee = 0;
                OiovCallback::ops_event_bill[no].sharp_total_elect = 0;
                OiovCallback::ops_event_bill[no].sharp_loss_calculation_elect = OiovCallback::ops_event_bill[no].sharp_total_elect;
                OiovCallback::ops_event_bill[no].sharp_total_fee = 0;
                OiovCallback::ops_event_bill[no].peak_unit_fee = 0;
                OiovCallback::ops_event_bill[no].peak_total_elect = 0;
                OiovCallback::ops_event_bill[no].peak_loss_calculation_elect = OiovCallback::ops_event_bill[no].peak_total_elect;
                OiovCallback::ops_event_bill[no].peak_total_fee = 0;
                OiovCallback::ops_event_bill[no].flat_unit_fee = 0;
                OiovCallback::ops_event_bill[no].flat_total_elect = 0;
                OiovCallback::ops_event_bill[no].flat_loss_calculation_elect = OiovCallback::ops_event_bill[no].flat_total_elect;
                OiovCallback::ops_event_bill[no].flat_total_fee = 0;
                OiovCallback::ops_event_bill[no].valley_unit_fee = 0;
                OiovCallback::ops_event_bill[no].valley_total_elect = 0;
                OiovCallback::ops_event_bill[no].valley_loss_calculation_elect = OiovCallback::ops_event_bill[no].valley_total_elect;
                OiovCallback::ops_event_bill[no].valley_total_fee = 0;
                memset(OiovCallback::ops_event_bill[no].total_meter_start, 0x00, sizeof(OiovCallback::ops_event_bill[no].total_meter_start));
                memset(OiovCallback::ops_event_bill[no].total_meter_stop, 0x00, sizeof(OiovCallback::ops_event_bill[no].total_meter_stop));
                OiovCallback::ops_event_bill[no].total_elect = 0;
                OiovCallback::ops_event_bill[no].total_loss_calculation_elect = OiovCallback::ops_event_bill[no].total_elect;
                OiovCallback::ops_event_bill[no].charging_fee = 0;
                memset(OiovCallback::ops_event_bill[no].vin, 0x00, sizeof(OiovCallback::ops_event_bill[no].vin));
                OiovCallback::ops_event_bill[no].transaction_type = OiovCallback::OPS_TRANSACTION_TYPE_APP; /* APP 启动充电 */
                OiovCallback::ops_event_bill[no].transaction_date = OiovCallback::ops_event_bill[no].stop_time;
                OiovCallback::ops_event_bill[no].stop_reason = OiovCallback::DEV_ABORT_CHARGING_CODE_83;
                memcpy(OiovCallback::ops_event_bill[no].physical_card_number, OiovCallback::ops_active_service_start_charging_app[no].physical_card_number, OPS_MAX_CARD_NUMBRE_LEN);

                // insert order
                vhash["proto_type"] = RecordMain::KYunKuaiChong;
                vhash["cp_type"] = RecordMain::KDeviceDC;
                str.clear();
                for (i = 0; i < sizeof(OiovCallback::ops_event_bill[no].pill_number); ++i) {
                    str += QString("%1").arg(OiovCallback::ops_event_bill[no].pill_number[i], 2, 16, QLatin1Char('0'));
                }
                vhash["pile_num"] = str;
                vhash["gnu_no"] = OiovCallback::ops_event_bill[no].gun_number;
                str.clear();
                for (i = 0; i < sizeof(OiovCallback::ops_event_bill[no].serial_number); ++i) {
                    str += QString("%1").arg(OiovCallback::ops_event_bill[no].serial_number[i], 2, 16, QLatin1Char('0'));
                }
                vhash["trade_no"] = str;
                vhash["start_type"] = OiovCallback::ops_event_bill[no].transaction_type;
                str.clear();
                for (i = 0; i < sizeof(OiovCallback::ops_event_bill[no].start_time.tm); ++i) {
                    str += QString("%1").arg(OiovCallback::ops_event_bill[no].start_time.tm[i], 2, 16, QLatin1Char('0')).toUpper();
                }
                vhash["start_time"] = str;
                str.clear();
                for (i = 0; i < sizeof(OiovCallback::ops_event_bill[no].stop_time.tm); ++i) {
                    str += QString("%1").arg(OiovCallback::ops_event_bill[no].stop_time.tm[i], 2, 16, QLatin1Char('0')).toUpper();
                }
                vhash["stop_time"] = str;
                vhash["stop_reason"] = OiovCallback::ops_event_bill[no].stop_reason;
                vhash["charging_time"] = 0; // No such field
                str.clear();
                for (i = 0; i < sizeof(OiovCallback::ops_event_bill[no].vin); ++i) {
                    str += QString("%1").arg(OiovCallback::ops_event_bill[no].vin[i], 2, 16, QLatin1Char('0'));
                }
                vhash["vin_code"] = str;
                str.clear();
                for (i = 0; i < sizeof(OiovCallback::ops_event_bill[no].physical_card_number); ++i) {
                    str += QString("%1").arg(OiovCallback::ops_event_bill[no].physical_card_number[i], 2, 16, QLatin1Char('0'));
                }
                vhash["card_code"] = str;
                vhash["sharp_elec_unit_fee"] = 0;
                vhash["sharp_service_unit_fee"] = 0;
                vhash["sharp_total_elect"] = 0;
                vhash["sharp_loss_elect"] = 0;
                vhash["sharp_elec_total_fee"] = 0;
                vhash["sharp_service_total_fee"] = 0;
                vhash["peak_elec_unit_fee"] = 0;
                vhash["peak_service_unit_fee"] = 0;
                vhash["peak_total_elect"] = 0;
                vhash["peak_loss_elect"] = 0;
                vhash["peak_elec_total_fee"] = 0;
                vhash["peak_service_total_fee"] = 0;
                vhash["flat_elec_unit_fee"] = 0;
                vhash["flat_service_unit_fee"] = 0;
                vhash["flat_total_elect"] = 0;
                vhash["flat_loss_elect"] = 0;
                vhash["flat_elec_total_fee"] = 0;
                vhash["flat_service_total_fee"] = 0;
                vhash["valley_elec_unit_fee"] = 0;
                vhash["valley_service_unit_fee"] = 0;
                vhash["valley_total_elect"] = 0;
                vhash["valley_loss_elect"] = 0;
                vhash["valley_elec_total_fee"] = 0;
                vhash["valley_service_total_fee"] = 0;
                vhash["total_meter_start"] = QString::number(0);
                vhash["total_meter_stop"] = QString::number(0);
                vhash["total_elect"] = 0;
                vhash["total_loss_elect"] = 0;
                vhash["total_elec_cost"] = 0;
                vhash["total_service_cost"] = 0;
                vhash["order_state"] = RecordMain::KOrderProcessing;
                RecordMain::m_baseRecord.InsertRecord(vhash);

                //设备状态 -> 桩开始充电
                OiovCallback::ops_property_charge_data[no].status = OiovCallback::OPS_CHARGINGPILE_STATE_CHARGING;
                //向平台发送设备状态事件
                OiovReqMain::SetDeviceStatusEvent(no);

                //开始充电中的属性上报
                OiovReqMain::SetChargingProperty(no);
            } else if (CardMain::StartChargeService(no)) {
                HciMain::ClearStartChargeService(no); //清除标志位
                HciMain::ClearStopChargeService(no); //清除标志位
                CardMain::ClearStartChargeService(no); //清除标志位
                CardMain::ClearStopChargeService(no); //清除标志位
                OiovReqMain::ClearAppStartChargeService(no); //清除标志位
                OiovReqMain::ClearAppStopChargeService(no); //清除标志位
                OiovReqMain::ClearCardAuthStartChargeService(no); //清除标志位
                ControllerParserMain::ClearStopChargingService(no); //清除标志位

                QString card_number = QString(CardMain::card_number());
                if (card_number == BaseConfigure::pile_model()) {
                    qDebug() << "[CHARGE]->" << (no ? "No.b" : "No.a") << "offline-card start charging ( start time:" << _time << ")";

                    g->set_card_number((char *)(CardMain::card_number().data()), CardMain::card_number().size()); // 填充卡号，用于充电中检测

                    g->set_start_time(_time);
                    g->set_stop_time(g->start_time());
                    g->set_charge_time(g->start_time() - g->stop_time());
                    g->set_start_timeout(START_TIMEOUT * 1000 / 100);

                    ChangeState(g, StartingStatus::instance()); //切换到开始充电

#if defined(READYSTATE_DEBUG)
                    qDebug() << "[CHARGE]->" << (no ? "No.b" : "No.a") << "ready -> starting";
#endif

                    //start charging - 告诉控制器可以开始充电了
                    ControllerSendMain::con_start_charg[no].gnu_no = no + CONGUNNOA;
                    ControllerSendMain::con_start_charg[no].ctrl_flag = 1; //1: Enable , 2: Disenable
                    ControllerSendMain::con_start_charg[no].aps = BaseConfigure::apu24(no) ? 0x02 : 0x01; //1: 12V , 2: 24V
                    memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_START_CHARG]), 0x00, sizeof(con_frame_info_t));
                    ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].gunno = no + CONGUNNOA;
                    ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].cycle = 250;
                    ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].count = 0;
                    ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].timeout = 5000;
                    ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].time = controller_time();
                    ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].pduformat = CON_PDUFORMAT_START_CHARG;

                    //data - 填充充电枪实时数据
                    memset(OiovCallback::ops_property_charge_data[no].serial_number, 0xFF, sizeof(OiovCallback::ops_property_charge_data[no].serial_number));
                    OiovCallback::ops_property_charge_data[no].connect_gun = OiovCallback::OPS_GUN_CONNECT_STATE_YES;
                    OiovCallback::ops_property_charge_data[no].output_voltage = 0x00;
                    OiovCallback::ops_property_charge_data[no].output_current = 0x00;
                    OiovCallback::ops_property_charge_data[no].line_temp = 50;
                    OiovCallback::ops_property_charge_data[no].soc = 0;
                    OiovCallback::ops_property_charge_data[no].battery_max_temp = 50;
                    OiovCallback::ops_property_charge_data[no].charging_time = 0x00;
                    OiovCallback::ops_property_charge_data[no].remaining_charging_time = 0x00;
                    OiovCallback::ops_property_charge_data[no].charging_elect = 0x00;
                    OiovCallback::ops_property_charge_data[no].loss_calculation_elect = OiovCallback::ops_property_charge_data[no].charging_elect;
                    OiovCallback::ops_property_charge_data[no].charging_fee = 0x00;
                    OiovCallback::ops_property_charge_data[no].fault = 0x00;

                    //data - 填充交易记录
                    OiovCallback::ops_event_bill[no].transaction_type = OiovCallback::OPS_TRANSACTION_TYPE_OFFCARD; /* 离线卡启动充电 */

                    //设备状态 -> 桩开始充电
                    OiovCallback::ops_property_charge_data[no].status = OiovCallback::OPS_CHARGINGPILE_STATE_CHARGING;
                    //向平台发送设备状态事件
                    OiovReqMain::SetDeviceStatusEvent(no);

                    //开始充电中的属性上报
                    OiovReqMain::SetChargingProperty(no);
                } else {
                    qDebug() << "[CHARGE]->" << (no ? "No.b" : "No.a") << "online-card authoraztion...";

                    g->set_card_number((char *)(CardMain::card_number().data()), CardMain::card_number().size()); // 填充卡号，用于充电中检测

                    // 填充权限验证（鉴权）
                    QByteArray card_number = CardMain::card_number();
                    OiovCallback::ops_event_card_authorize[no].start_mode = 0x01; /* 通过刷卡启动充电 */
                    OiovCallback::ops_event_card_authorize[no].whether_need_password = 0x00;
                    OiovCallback::ops_event_card_authorize[no].physical_card_number[0] = 0x00;
                    OiovCallback::ops_event_card_authorize[no].physical_card_number[1] = 0x00;
                    OiovCallback::ops_event_card_authorize[no].physical_card_number[2] = 0x00;
                    OiovCallback::ops_event_card_authorize[no].physical_card_number[3] = 0x00;
                    OiovCallback::ops_event_card_authorize[no].physical_card_number[4] = card_number[3];
                    OiovCallback::ops_event_card_authorize[no].physical_card_number[5] = card_number[2];
                    OiovCallback::ops_event_card_authorize[no].physical_card_number[6] = card_number[1];
                    OiovCallback::ops_event_card_authorize[no].physical_card_number[7] = card_number[0];
                    memset(OiovCallback::ops_event_card_authorize[no].password, 0x00, sizeof(OiovCallback::ops_event_card_authorize[no].password));
                    memset(OiovCallback::ops_event_card_authorize[no].vin, 0x00, sizeof(OiovCallback::ops_event_card_authorize[no].vin));
                    //向平台发送向平台发送卡鉴权
                    OiovReqMain::SetCardAuthChargeEvent(no);
                }
            } else if (OiovReqMain::CardAuthStartChargeService(no)) {
                HciMain::ClearStartChargeService(no); //清除标志位
                HciMain::ClearStopChargeService(no); //清除标志位
                CardMain::ClearStartChargeService(no); //清除标志位
                CardMain::ClearStopChargeService(no); //清除标志位
                OiovReqMain::ClearAppStartChargeService(no); //清除标志位
                OiovReqMain::ClearAppStopChargeService(no); //清除标志位
                OiovReqMain::ClearCardAuthStartChargeService(no); //清除标志位
                ControllerParserMain::ClearStopChargingService(no); //清除标志位

                if (0x01 != OiovCallback::ops_passive_service_card_authorize[no].authentication_flag) {
                    return;
                }

                qDebug() << "[CHARGE]->" << (no ? "No.b" : "No.a") << "online-card start charging ( start time:" << _time << ")";

                g->set_start_time(_time);
                g->set_stop_time(g->start_time());
                g->set_charge_time(g->start_time() - g->stop_time());
                g->set_start_timeout(START_TIMEOUT * 1000 / 100);

                ChangeState(g, StartingStatus::instance()); //切换到开始充电

#if defined(READYSTATE_DEBUG)
                qDebug() << "[CHARGE]->" << (no ? "No.b" : "No.a") << "ready -> starting";
#endif

                //start charging - 告诉控制器可以开始充电了
                ControllerSendMain::con_start_charg[no].gnu_no = no + CONGUNNOA;
                ControllerSendMain::con_start_charg[no].ctrl_flag = 1; //1: Enable , 2: Disenable
                ControllerSendMain::con_start_charg[no].aps = BaseConfigure::apu24(no) ? 0x02 : 0x01; //1: 12V , 2: 24V
                memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_START_CHARG]), 0x00, sizeof(con_frame_info_t));
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].gunno = no + CONGUNNOA;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].cycle = 250;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].count = 0;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].timeout = 5000;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].time = controller_time();
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].pduformat = CON_PDUFORMAT_START_CHARG;

                //data - 填充充电枪实时数据
                memset(OiovCallback::ops_property_charge_data[no].serial_number, 0x00, sizeof(OiovCallback::ops_property_charge_data[no].serial_number));
                memcpy(OiovCallback::ops_property_charge_data[no].serial_number, OiovCallback::ops_passive_service_card_authorize[no].serial_number, sizeof(OiovCallback::ops_property_charge_data[no].serial_number));
                memset(OiovCallback::ops_property_charge_data[no].pill_number, 0x00, sizeof(OiovCallback::ops_event_bill[no].pill_number));
                memcpy(OiovCallback::ops_property_charge_data[no].pill_number, OiovCallback::ops_passive_service_card_authorize[no].pill_number, sizeof(OiovCallback::ops_property_charge_data[no].pill_number));
                OiovCallback::ops_property_charge_data[no].connect_gun = OiovCallback::OPS_GUN_CONNECT_STATE_YES;
                OiovCallback::ops_property_charge_data[no].output_voltage = 0x00;
                OiovCallback::ops_property_charge_data[no].output_current = 0x00;
                OiovCallback::ops_property_charge_data[no].line_temp = 50;
                OiovCallback::ops_property_charge_data[no].soc = 0;
                OiovCallback::ops_property_charge_data[no].battery_max_temp = 50;
                OiovCallback::ops_property_charge_data[no].charging_time = 0x00;
                OiovCallback::ops_property_charge_data[no].remaining_charging_time = 0x00;
                OiovCallback::ops_property_charge_data[no].charging_elect = 0x00;
                OiovCallback::ops_property_charge_data[no].loss_calculation_elect = OiovCallback::ops_property_charge_data[no].charging_elect;
                OiovCallback::ops_property_charge_data[no].charging_fee = 0x00;
                OiovCallback::ops_property_charge_data[no].fault = 0x00;

                //data - 填充交易记录
                memset(OiovCallback::ops_event_bill[no].serial_number, 0x00, sizeof(OiovCallback::ops_event_bill[no].serial_number));
                memcpy(OiovCallback::ops_event_bill[no].serial_number, OiovCallback::ops_passive_service_card_authorize[no].serial_number, sizeof(OiovCallback::ops_event_bill[no].serial_number));
                memset(OiovCallback::ops_event_bill[no].pill_number, 0x00, sizeof(OiovCallback::ops_event_bill[no].pill_number));
                memcpy(OiovCallback::ops_event_bill[no].pill_number, OiovCallback::ops_passive_service_card_authorize[no].pill_number, sizeof(OiovCallback::ops_event_bill[no].pill_number));
                OiovCallback::ops_event_bill[no].start_time.cp56time2a_tm.year  = _tm->tm_year + 1900 - 2000;
                OiovCallback::ops_event_bill[no].start_time.cp56time2a_tm.month = _tm->tm_mon + 1;
                OiovCallback::ops_event_bill[no].start_time.cp56time2a_tm.mday  = _tm->tm_mday;
                OiovCallback::ops_event_bill[no].start_time.cp56time2a_tm.wday  = _tm->tm_wday;
                OiovCallback::ops_event_bill[no].start_time.cp56time2a_tm.hour  = _tm->tm_hour;
                OiovCallback::ops_event_bill[no].start_time.cp56time2a_tm.min   = _tm->tm_min;
                OiovCallback::ops_event_bill[no].start_time.cp56time2a_tm.msec  = _tm->tm_sec * 1000;
                OiovCallback::ops_event_bill[no].stop_time = OiovCallback::ops_event_bill[no].start_time;
                OiovCallback::ops_event_bill[no].sharp_unit_fee = 0;
                OiovCallback::ops_event_bill[no].sharp_total_elect = 0;
                OiovCallback::ops_event_bill[no].sharp_loss_calculation_elect = OiovCallback::ops_event_bill[no].sharp_total_elect;
                OiovCallback::ops_event_bill[no].sharp_total_fee = 0;
                OiovCallback::ops_event_bill[no].peak_unit_fee = 0;
                OiovCallback::ops_event_bill[no].peak_total_elect = 0;
                OiovCallback::ops_event_bill[no].peak_loss_calculation_elect = OiovCallback::ops_event_bill[no].peak_total_elect;
                OiovCallback::ops_event_bill[no].peak_total_fee = 0;
                OiovCallback::ops_event_bill[no].flat_unit_fee = 0;
                OiovCallback::ops_event_bill[no].flat_total_elect = 0;
                OiovCallback::ops_event_bill[no].flat_loss_calculation_elect = OiovCallback::ops_event_bill[no].flat_total_elect;
                OiovCallback::ops_event_bill[no].flat_total_fee = 0;
                OiovCallback::ops_event_bill[no].valley_unit_fee = 0;
                OiovCallback::ops_event_bill[no].valley_total_elect = 0;
                OiovCallback::ops_event_bill[no].valley_loss_calculation_elect = OiovCallback::ops_event_bill[no].valley_total_elect;
                OiovCallback::ops_event_bill[no].valley_total_fee = 0;
                memset(OiovCallback::ops_event_bill[no].total_meter_start, 0x00, sizeof(OiovCallback::ops_event_bill[no].total_meter_start));
                memset(OiovCallback::ops_event_bill[no].total_meter_stop, 0x00, sizeof(OiovCallback::ops_event_bill[no].total_meter_stop));
                OiovCallback::ops_event_bill[no].total_elect = 0;
                OiovCallback::ops_event_bill[no].total_loss_calculation_elect = OiovCallback::ops_event_bill[no].total_elect;
                OiovCallback::ops_event_bill[no].charging_fee = 0;
                memset(OiovCallback::ops_event_bill[no].vin, 0x00, sizeof(OiovCallback::ops_event_bill[no].vin));
                OiovCallback::ops_event_bill[no].transaction_type = OiovCallback::OPS_TRANSACTION_TYPE_ONCARD; /* 在线卡启动充电 */
                OiovCallback::ops_event_bill[no].transaction_date = OiovCallback::ops_event_bill[no].stop_time;
                OiovCallback::ops_event_bill[no].stop_reason = OiovCallback::DEV_ABORT_CHARGING_CODE_83;
                memcpy(OiovCallback::ops_event_bill[no].physical_card_number, OiovCallback::ops_event_card_authorize[no].physical_card_number, OPS_MAX_CARD_NUMBRE_LEN);

                // insert order
                vhash["proto_type"] = RecordMain::KYunKuaiChong;
                vhash["cp_type"] = RecordMain::KDeviceDC;
                str.clear();
                for (i = 0; i < sizeof(OiovCallback::ops_event_bill[no].pill_number); ++i) {
                    str += QString("%1").arg(OiovCallback::ops_event_bill[no].pill_number[i], 2, 16, QLatin1Char('0'));
                }
                vhash["pile_num"] = str;
                vhash["gnu_no"] = OiovCallback::ops_event_bill[no].gun_number;
                str.clear();
                for (i = 0; i < sizeof(OiovCallback::ops_event_bill[no].serial_number); ++i) {
                    str += QString("%1").arg(OiovCallback::ops_event_bill[no].serial_number[i], 2, 16, QLatin1Char('0'));
                }
                vhash["trade_no"] = str;
                vhash["start_type"] = OiovCallback::ops_event_bill[no].transaction_type;
                str.clear();
                for (i = 0; i < sizeof(OiovCallback::ops_event_bill[no].start_time.tm); ++i) {
                    str += QString("%1").arg(OiovCallback::ops_event_bill[no].start_time.tm[i], 2, 16, QLatin1Char('0')).toUpper();
                }
                vhash["start_time"] = str;
                str.clear();
                for (i = 0; i < sizeof(OiovCallback::ops_event_bill[no].stop_time.tm); ++i) {
                    str += QString("%1").arg(OiovCallback::ops_event_bill[no].stop_time.tm[i], 2, 16, QLatin1Char('0')).toUpper();
                }
                vhash["stop_time"] = str;
                vhash["stop_reason"] = OiovCallback::ops_event_bill[no].stop_reason;
                vhash["charging_time"] = 0; // No such field
                str.clear();
                for (i = 0; i < sizeof(OiovCallback::ops_event_bill[no].vin); ++i) {
                    str += QString("%1").arg(OiovCallback::ops_event_bill[no].vin[i], 2, 16, QLatin1Char('0'));
                }
                vhash["vin_code"] = str;
                str.clear();
                for (i = 0; i < sizeof(OiovCallback::ops_event_bill[no].physical_card_number); ++i) {
                    str += QString("%1").arg(OiovCallback::ops_event_bill[no].physical_card_number[i], 2, 16, QLatin1Char('0'));
                }
                vhash["card_code"] = str;
                vhash["sharp_elec_unit_fee"] = 0;
                vhash["sharp_service_unit_fee"] = 0;
                vhash["sharp_total_elect"] = 0;
                vhash["sharp_loss_elect"] = 0;
                vhash["sharp_elec_total_fee"] = 0;
                vhash["sharp_service_total_fee"] = 0;
                vhash["peak_elec_unit_fee"] = 0;
                vhash["peak_service_unit_fee"] = 0;
                vhash["peak_total_elect"] = 0;
                vhash["peak_loss_elect"] = 0;
                vhash["peak_elec_total_fee"] = 0;
                vhash["peak_service_total_fee"] = 0;
                vhash["flat_elec_unit_fee"] = 0;
                vhash["flat_service_unit_fee"] = 0;
                vhash["flat_total_elect"] = 0;
                vhash["flat_loss_elect"] = 0;
                vhash["flat_elec_total_fee"] = 0;
                vhash["flat_service_total_fee"] = 0;
                vhash["valley_elec_unit_fee"] = 0;
                vhash["valley_service_unit_fee"] = 0;
                vhash["valley_total_elect"] = 0;
                vhash["valley_loss_elect"] = 0;
                vhash["valley_elec_total_fee"] = 0;
                vhash["valley_service_total_fee"] = 0;
                vhash["total_meter_start"] = QString::number(0);
                vhash["total_meter_stop"] = QString::number(0);
                vhash["total_elect"] = 0;
                vhash["total_loss_elect"] = 0;
                vhash["total_elec_cost"] = 0;
                vhash["total_service_cost"] = 0;
                vhash["order_state"] = RecordMain::KOrderProcessing;
                RecordMain::m_baseRecord.InsertRecord(vhash);

                //设备状态 -> 桩开始充电
                OiovCallback::ops_property_charge_data[no].status = OiovCallback::OPS_CHARGINGPILE_STATE_CHARGING;
                //向平台发送设备状态事件
                OiovReqMain::SetDeviceStatusEvent(no);

                //开始充电中的属性上报
                OiovReqMain::SetChargingProperty(no);
            } else if (HciMain::StartChargeService(no)) {
                HciMain::ClearStartChargeService(no); //清除标志位
                HciMain::ClearStopChargeService(no); //清除标志位
                CardMain::ClearStartChargeService(no); //清除标志位
                CardMain::ClearStopChargeService(no); //清除标志位
                OiovReqMain::ClearAppStartChargeService(no); //清除标志位
                OiovReqMain::ClearAppStopChargeService(no); //清除标志位
                OiovReqMain::ClearCardAuthStartChargeService(no); //清除标志位
                ControllerParserMain::ClearStopChargingService(no); //清除标志位

                qDebug() << "[CHARGE]->" << (no ? "No.b" : "No.a") << "hci start charging ( start time:" << _time << ")";

                g->set_start_time(_time);
                g->set_stop_time(g->start_time());
                g->set_charge_time(g->start_time() - g->stop_time());
                g->set_start_timeout(START_TIMEOUT * 1000 / 100);

                ChangeState(g, StartingStatus::instance()); //切换到开始充电

#if defined(READYSTATE_DEBUG)
                qDebug() << "[CHARGE]->" << (no ? "No.b" : "No.a") << "ready -> starting";
#endif

                //start charging - 告诉控制器可以开始充电了
                ControllerSendMain::con_start_charg[no].gnu_no = no + CONGUNNOA;
                ControllerSendMain::con_start_charg[no].ctrl_flag = 1; //1: Enable , 2: Disenable
                ControllerSendMain::con_start_charg[no].aps = BaseConfigure::apu24(no) ? 0x02 : 0x01; //1: 12V , 2: 24V
                memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_START_CHARG]), 0x00, sizeof(con_frame_info_t));
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].gunno = no + CONGUNNOA;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].cycle = 250;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].count = 0;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].timeout = 5000;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].time = controller_time();
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_START_CHARG].pduformat = CON_PDUFORMAT_START_CHARG;

                //data - 填充充电枪实时数据
                memset(OiovCallback::ops_property_charge_data[no].serial_number, 0xFF, sizeof(OiovCallback::ops_property_charge_data[no].serial_number));
                OiovCallback::ops_property_charge_data[no].connect_gun = OiovCallback::OPS_GUN_CONNECT_STATE_YES;
                OiovCallback::ops_property_charge_data[no].output_voltage = 0x00;
                OiovCallback::ops_property_charge_data[no].output_current = 0x00;
                OiovCallback::ops_property_charge_data[no].line_temp = 50;
                OiovCallback::ops_property_charge_data[no].soc = 0;
                OiovCallback::ops_property_charge_data[no].battery_max_temp = 50;
                OiovCallback::ops_property_charge_data[no].charging_time = 0x00;
                OiovCallback::ops_property_charge_data[no].remaining_charging_time = 0x00;
                OiovCallback::ops_property_charge_data[no].charging_elect = 0x00;
                OiovCallback::ops_property_charge_data[no].loss_calculation_elect = OiovCallback::ops_property_charge_data[no].charging_elect;
                OiovCallback::ops_property_charge_data[no].charging_fee = 0x00;
                OiovCallback::ops_property_charge_data[no].fault = 0x00;

                //data - 填充交易记录
                OiovCallback::ops_event_bill[no].transaction_type = OiovCallback::OPS_TRANSACTION_TYPE_HCI; /* HCI 启动充电 */

                //设备状态 -> 桩开始充电
                OiovCallback::ops_property_charge_data[no].status = OiovCallback::OPS_CHARGINGPILE_STATE_CHARGING;
                //向平台发送设备状态事件
                OiovReqMain::SetDeviceStatusEvent(no);

                //开始充电中的属性上报
                OiovReqMain::SetChargingProperty(no);
            } else {
                //...
            }
        } else {
            ChangeState(g, IdleStatus::instance()); //切换到插枪准备

#if defined(READYSTATE_DEBUG)
            qDebug() << "[CHARGE]->" << (no ? "No.b" : "No.a") << "ready -> idle";
#endif

            //设备状态 -> 空闲中
            memset(OiovCallback::ops_property_charge_data[no].serial_number, 0x00, sizeof(OiovCallback::ops_property_charge_data[no].serial_number));
            OiovCallback::ops_property_charge_data[no].status = OiovCallback::OPS_CHARGINGPILE_STATE_IDLE;
            OiovCallback::ops_property_charge_data[no].connect_gun = OiovCallback::OPS_GUN_CONNECT_STATE_NOT;
            OiovCallback::ops_property_charge_data[no].output_voltage = 0x00;
            OiovCallback::ops_property_charge_data[no].output_current = 0x00;
            OiovCallback::ops_property_charge_data[no].line_temp = 0x00;
            OiovCallback::ops_property_charge_data[no].soc = 0x00;
            OiovCallback::ops_property_charge_data[no].battery_max_temp = 0x00;
            OiovCallback::ops_property_charge_data[no].charging_time = 0x00;
            OiovCallback::ops_property_charge_data[no].remaining_charging_time = 0x00;
            OiovCallback::ops_property_charge_data[no].charging_elect = 0x00;
            OiovCallback::ops_property_charge_data[no].loss_calculation_elect = OiovCallback::ops_property_charge_data[no].charging_elect;
            OiovCallback::ops_property_charge_data[no].charging_fee = 0x00;
            OiovCallback::ops_property_charge_data[no].fault = 0x00;
            //向平台发送设备状态事件
            OiovReqMain::SetDeviceStatusEvent(no);
        }
        break;
    case CONF_STATE:
        break;
    case FULL_STATE:
        break;
    case CHARGING_STATE:
        break;
    case WARRING_STATE:
        break;
    case FAULT_STATE:
        ChangeState(g, FaultStatus::instance()); //切换到故障

#if defined(READYSTATE_DEBUG)
        qDebug() << "[CHARGE]->" << (no ? "No.b" : "No.a") << "ready -> fault";
#endif

        //设备状态 -> 故障中
        memset(OiovCallback::ops_property_charge_data[no].serial_number, 0x00, sizeof(OiovCallback::ops_property_charge_data[no].serial_number));
        OiovCallback::ops_property_charge_data[no].status = OiovCallback::OPS_CHARGINGPILE_STATE_FAULT;
        OiovCallback::ops_property_charge_data[no].connect_gun = OiovCallback::OPS_GUN_CONNECT_STATE_YES;
        OiovCallback::ops_property_charge_data[no].output_voltage = 0x00;
        OiovCallback::ops_property_charge_data[no].output_current = 0x00;
        OiovCallback::ops_property_charge_data[no].line_temp = 0x00;
        OiovCallback::ops_property_charge_data[no].soc = 0x00;
        OiovCallback::ops_property_charge_data[no].battery_max_temp = 0x00;
        OiovCallback::ops_property_charge_data[no].charging_time = 0x00;
        OiovCallback::ops_property_charge_data[no].remaining_charging_time = 0x00;
        OiovCallback::ops_property_charge_data[no].charging_elect = 0x00;
        OiovCallback::ops_property_charge_data[no].loss_calculation_elect = OiovCallback::ops_property_charge_data[no].charging_elect;
        OiovCallback::ops_property_charge_data[no].charging_fee = 0x00;
        OiovCallback::ops_property_charge_data[no].fault = 0x00;
        //向平台发送设备状态事件
        OiovReqMain::SetDeviceStatusEvent(no);
        break;
    default:
        break;
    }
}
